package com.encyclopedia.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.encyclopedia.auth.UserDetailEntity;
import com.encyclopedia.entity.User;
import com.encyclopedia.mapper.UserMapper;
import com.encyclopedia.properties.SystemProperties;
import com.encyclopedia.result.exception.ServiceException;
import com.encyclopedia.result.exenum.RequestException;
import com.encyclopedia.service.RedisUtils;
import com.encyclopedia.service.UserService;
import com.encyclopedia.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author MaLiang
 * @version 1.0
 * @date 2024-04-27 16:33
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private SystemProperties systemProperties;

    @Autowired
    private PasswordEncoder bCryptPasswordEncoder;

    /**
     * 查询所有用户
     *
     * @return
     */
    @Override
    public List<User> selectlist() {
        //查询所有用户
        return userMapper.selectlist();
    }

    /**
     * 修改用户信息
     *
     * @param user
     * @return
     */
    @Override
    public int updateById(User user) {
        Integer userId = user.getUserId();
        user.setUserId(userId);
        return userMapper.UpdateUser(user);
    }

    /**
     * 回显
     *
     * @param id
     * @return
     */
    @Override
    public User getById(Integer id) {
        return userMapper.selectUserById(id);
    }


    /**
     * 修改/重置密码
     *
     * @param user 用户信息
     * @return JSON
     */
    @Override
    public Integer updateUserPassword(User user) {
        //密码和新密码必须存在
        if (!StringUtils.hasText(user.getPassword()) ||
                !StringUtils.hasText(user.getNewPassword())) {
            throw new ServiceException(RequestException.UPDATE_ERROR);
        }
        User user1 = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, user.getUsername())
        );
        if (Objects.isNull(user1)) {
            throw new ServiceException(RequestException.NOT_FOUND);
        }
        if (!bCryptPasswordEncoder.matches(user.getPassword(), user1.getPassword())) {
            throw new ServiceException(RequestException.NOT_FOUND);
        }
        //加密密码
        String encode = bCryptPasswordEncoder.encode(user.getNewPassword());
        user.setPassword(encode);
        //传入ID
        user.setUserId(user1.getUserId());
        int column = userMapper.updatePassword(user);
        if (column < 1) {
            throw new ServiceException(RequestException.UPDATE_ERROR);
        }
        redisUtils.del(systemProperties.getTokenKey() + user1.getUserId());
        return column;
    }

    /**
     * 根据token获取用户信息
     *
     * @param token token
     * @return 用户信息
     */
    @Override
    public User getUserByToken(String token) {
        Integer id = TokenUtils.checkToken(token, Integer.class);
        User user = userMapper.selectUserById(id);
        if (Objects.isNull(user)) {
            throw new ServiceException(RequestException.NOT_FOUND);
        }
        UserDetailEntity userDetailEntity = new UserDetailEntity(user);
        userDetailEntity.setUser(user);
        userDetailEntity.setPermissionList(Collections.singletonList(user.getRole()));
        //存入
        UsernamePasswordAuthenticationToken ut = new UsernamePasswordAuthenticationToken(
                userDetailEntity, user.getPassword(), userDetailEntity.getAuthorities());
        //将权限信息放入SecurityContextHolder
        SecurityContextHolder.getContextHolderStrategy()
                .getContext().setAuthentication(ut);
        //存储当前用户信息
        redisUtils.set(systemProperties.getMapKey(),
                user.getUserId().toString(), 5 * 60 * 60);//value: 用户序列化后的字符串
        //将用户信息存入Redis数据库
        redisUtils.set(
                systemProperties.getTokenKey() + user.getUserId(), //key: login:2(数字代表ID)
                JSON.toJSONString(userDetailEntity), 5 * 60 * 60);//value: 用户序列化后的字符串
        return user;
    }


}
